# -*- coding: utf-8 -*-
# @Time         : 12:26 2025/2/25
# @Author       : Chris
# @Description  :
from __future__ import annotations

from typing import List, Optional, Iterable, Dict

import httpx

from .._base_client import (
    make_request_options,
)
from .._models import BaseModel
from .._resource import SyncAPIResource
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from ..pagination import SyncPage
from ..types.product_category import ProductCategory, Industry
from ..types.product import ProductType
from ..types.product import SaleStatusEnum
from ..types.product_batch_create_response import ProductBatchCreateResponse
from ..types.product_create_params import ProductCreationParams
from ..types.product_create_response import ProductCreationResponse
from ..types.product_detail import ProductDetail
from ..types.product_edit_params import ProductEditParams
from ..types.product_edit_stock_params import ProductEditStockParams
from ..types.product_profile import ProductProfile
from ..types.product_property import ProductProperty
from ..types.product_sku import ProductSkus
from ..types.product import FlashSaleType

__all__ = ["Products"]


class Products(SyncAPIResource):
    def list_categories(
            self,
            product_type: ProductType,
            industry: Industry = None,
            flash_sale_type: FlashSaleType = None,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> SyncPage[ProductCategory]:
        return self._post_api_list(
            "/product/category/list",
            page=SyncPage[ProductCategory],
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            model=ProductCategory,
            body={"item_biz_type": product_type, "sp_biz_type": industry, "flash_sale_type": flash_sale_type}
        )

    def list_properties(
            self,
            product_type: ProductType,
            industry: Industry,
            channel_cat_id: str,
            sub_property_id: str = None,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> SyncPage[ProductProperty]:
        return self._post_api_list(
            "/product/pv/list",
            page=SyncPage[ProductProperty],
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            model=ProductProperty,
            body={
                "channel_cat_id": channel_cat_id,
                "item_biz_type": product_type,
                "sp_biz_type": industry,
                "sub_property_id": sub_property_id,
            }
        )

    def list(
            self,
            page_no: int,
            page_size: int,
            create_time: Optional[List[int]] = None,
            offline_time: Optional[List[int]] = None,
            online_time: Optional[List[int]] = None,
            product_status: Optional[int] = None,
            sale_status: Optional[SaleStatusEnum] = None,
            sold_time: Optional[List[int]] = None,
            update_time: Optional[List[int]] = None,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> SyncPage[ProductProfile]:
        """
        查询符合条件的商品。

        :param create_time: 商品创建时间
        :param offline_time: 商品下架时间
        :param online_time: 商品上架时间
        :param page_no: 页码
        :param page_size: 每页行数
        :param product_status: 管家商品状态
        :param sale_status: 销售状态
        :param sold_time: 商品售罄时间
        :param update_time: 商品更新时间
        :return: 包含所有参数的字典
        """
        return self._post_api_list(
            "/product/list",
            page=SyncPage[ProductProfile],
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            model=ProductProfile,
            body={
                "create_time": create_time,
                "offline_time": offline_time,
                "online_time": online_time,
                "page_no": page_no,
                "page_size": page_size,
                "product_status": product_status,
                "sale_status": sale_status.value if sale_status else None,
                "sold_time": sold_time,
                "update_time": update_time,
            },
        )

    def detail(
            self,
            product_id: int,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> ProductDetail:
        """
        Retrieves a model instance, providing basic information about the model such as
        the owner and permissioning.

        Args:
          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        return self._post(
            f"/product/detail",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=ProductDetail,
            body={"product_id": product_id}
        )

    def list_skus(
            self,
            product_ids: List[int],
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> SyncPage[ProductSkus]:
        return self._post_api_list(
            "/product/sku/list",
            page=SyncPage[ProductSkus],
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            model=ProductSkus,
            body={"product_id": product_ids}
        )

    def create(
            self,
            product: ProductCreationParams,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> ProductCreationResponse:
        """
        Lists the currently available shops, and provides basic information about each
        one such as the owner and availability.
        """
        return self._post(
            "/product/create",
            body=product.model_dump(),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=ProductCreationResponse
        )

    def batch_create(
            self,
            products: List[ProductCreationParams],
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> ProductBatchCreateResponse:
        """
        Lists the currently available shops, and provides basic information about each
        one such as the owner and availability.
        """
        return self._post(
            "/product/batchCreate",
            body={"product_data": [x.model_dump() for x in products]},
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=ProductBatchCreateResponse
        )

    def publish(
            self,
            product_id: int,
            user_name: List[str],
            notify_url: Optional[str] = None,
            specify_publish_time: Optional[str] = None,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ):
        """
        商品上架。

        :param product_id: 管家商品ID
        :param user_name: 闲鱼会员名（列表形式）
        :param notify_url: 上架回调地址
        :param specify_publish_time: 定时上架时间
        :return: 包含所有参数的字典
        """
        return self._post(
            "/product/publish",
            body={
                "product_id": product_id,
                "user_name": user_name,
                "notify_url": notify_url,
                "specify_publish_time": specify_publish_time,
            },
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=BaseModel
        )

    def unpublish(
            self,
            product_id: int,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ):
        """
        下架商品。
        """
        return self._post(
            "/product/downShelf",
            body={"product_id": product_id},
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=BaseModel
        )

    def edit(
            self,
            product: ProductEditParams,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> ProductCreationResponse:
        """
        Lists the currently available shops, and provides basic information about each
        one such as the owner and availability.
        """
        return self._post(
            "/product/edit",
            body=product.model_dump(),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=ProductCreationResponse
        )

    def edit_stock(
            self,
            stock: ProductEditStockParams,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ) -> ProductCreationResponse:
        """
        Lists the currently available shops, and provides basic information about each
        one such as the owner and availability.
        """
        return self._post(
            "/product/edit/stock",
            body=stock.model_dump(),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=BaseModel
        )

    def delete(
            self,
            product_id: int,
            *,
            # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
            # The extra values given here take precedence over values defined on the client or passed to this method.
            extra_headers: Headers | None = None,
            extra_query: Query | None = None,
            extra_body: Body | None = None,
            timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
    ):
        """
        删除商品。
        """
        return self._post(
            "/product/delete",
            body={"product_id": product_id},
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=BaseModel
        )

    def list_all(
            self,
            create_time: Optional[List[int]] = None,
            offline_time: Optional[List[int]] = None,
            online_time: Optional[List[int]] = None,
            product_status: Optional[int] = None,
            sale_status: Optional[SaleStatusEnum] = None,
            sold_time: Optional[List[int]] = None,
            update_time: Optional[List[int]] = None) -> List[ProductProfile]:
        """
        查询所有符合条件的产品。
        :param create_time:
        :param offline_time:
        :param online_time:
        :param product_status:
        :param sale_status:
        :param sold_time:
        :param update_time:
        :return:
        """
        profiles = []
        for i in range(99999999):
            page = self.list(i + 1, 100, create_time, offline_time, online_time, product_status, sale_status, sold_time, update_time)
            profiles.extend(page.list)
            if len(profiles) == page.count:
                break
        return profiles

    def list3oids(self, outer_ids: Iterable[str]) -> Dict[str, ProductProfile]:
        """
        使用商家编码查询产品简介。
        """
        oid_set = set(outer_ids)
        page_size = min(max(len(oid_set), 40), 100)
        oid2profile = {}
        item_cnt = 0
        for i in range(99999999):
            page = self.list(i + 1, page_size)
            for profile in page.list:
                if profile.outer_id in oid_set:
                    oid2profile[profile.outer_id] = profile
                    oid_set.remove(profile.outer_id)
                    if len(oid_set) == 0:
                        return oid2profile
            item_cnt += len(page.list)
            if item_cnt == page.count:
                break
        return oid2profile

    def detail3oids(self, outer_ids: Iterable[str]) -> Dict[str, ProductDetail]:
        """
        使用商家编码查询产品详情。
        """
        oid2profile = self.list3oids(outer_ids)
        return {
            oid: self.detail(profile.product_id)
            for oid, profile in oid2profile.items()
        }

    def publish3oids(self, outer_ids: Iterable[str], user_names: List[str],
                     notify_url: str = None,
                     specify_publish_time: int = None):
        """
        根据商家编码发布商品。
        """
        oid2profile = self.list3oids(outer_ids)
        for profile in oid2profile.values():
            self.publish(profile.product_id, user_names, notify_url, specify_publish_time)

    def unpublish3oids(self, outer_ids: Iterable[str]):
        """
        根据商家编码下架商品。
        """
        oid2profile = self.list3oids(outer_ids)
        for profile in oid2profile.values():
            self.unpublish(profile.product_id)

    def delete3oids(self, outer_ids: Iterable[str]):
        """
        根据商家编码删除商品。
        """
        oid2profile = self.list3oids(outer_ids)
        for profile in oid2profile.values():
            self.delete(profile.product_id)
